package com.joinway.framework.admin.core.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.joinway.framework.admin.bean.UserContext;
import com.joinway.framework.admin.bean.domain.AdminRole;
import com.joinway.framework.admin.bean.domain.AdminUser;
import com.joinway.framework.admin.bean.domain.AdminUserRole;
import com.joinway.framework.admin.bean.domain.RoleTreeMenu;
import com.joinway.framework.admin.bean.domain.TreeMenu;
import com.joinway.framework.admin.bean.view.LoginRole;
import com.joinway.framework.admin.bean.view.UserOverviewView;
import com.joinway.framework.admin.core.bean.view.Menu;
import com.joinway.framework.admin.core.bean.view.MenuListView;
import com.joinway.framework.admin.core.bean.view.TreeMenuView;
import com.joinway.framework.admin.core.utils.UIHelper;
import com.joinway.framework.bean.domain.constant.DomainConstants;
import com.joinway.framework.bean.exception.ValidationException;
import com.joinway.framework.bean.logging.annotation.InputLog;
import com.joinway.framework.bean.view.View;
import com.joinway.framework.core.repository.SystemConfigRepository;
import com.joinway.framework.core.utils.AppEnv;
import com.joinway.framework.extension.cipher.MD5;
import com.joinway.framework.extension.utils.DataUtils;


@Service
public class AdminService extends AbstractAdminService implements IAdminService {
	private final static Logger log = LoggerFactory.getLogger(AdminService.class);

	public static final String SUPERROLE_NAME = "SUPER";
	
	private static final String ADMIN_USER_SQL = "select * from admin_user where login_name = ? and password = ?";
	
//	@Autowired protected AdminQueryService qservice;
	
//	@Autowired protected TableRepository repository;

	@Autowired protected SystemConfigRepository systemRepository;
	
	@Transactional(rollbackFor=Throwable.class)
	public UserContext login(String name, String password, HttpServletRequest request) throws Exception {
		List<AdminUser> users = repository.find(AdminUser.class, ADMIN_USER_SQL, name, MD5.encrypt(password, name));

		AdminUser adminUser = CollectionUtils.isNotEmpty(users) ? users.get(0) : null;
		
		if (adminUser == null) {
			throw new ValidationException("user name  or password incorrect");
		}

		UserContext context = super.postLogin(adminUser, request);
		
//		adminUser.setLoginCount(adminUser.getLoginCount() + 1);
//		adminUser.setLastLoginTime(new Date());
//		
//		repository.save(adminUser);
//		
//		UserContext context = new UserContext();
//		context.setUser(adminUser);
//		
//		List<LoginRole> roles = qservice.findLoginRoles(adminUser.getId());
//		context.setRoles(roles);
		
		return context;
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	@InputLog
	public TreeMenuView getNavigatorMenus(int userId) throws Exception {
		List<TreeMenu> trees = null;

		List<String> roleNames = qservice.findRoleNames(userId);
		
		if(CollectionUtils.isNotEmpty(roleNames) && roleNames.contains(SUPERROLE_NAME)){
			trees = qservice.findTreeMenus();
			trees = Arrays.asList(trees.stream()
					.filter(t -> AppEnv.getAppId().equals(t.getAppId()))
					.toArray(TreeMenu[]::new));
		}else{
			trees = qservice.findTreeMenus(userId);
		}

		TreeMenuView view = new TreeMenuView();

		String pageSuffix = systemRepository.getStringValue(SystemConfigRepository.PageRequestSuffix);
		
		List<Menu> menus = UIHelper.convert(trees, pageSuffix);
		view.setMenus(menus);

		return view;
	}

	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	@InputLog
	public TreeMenuView getRoleMenus(String roleId) throws Exception {
		List<RoleTreeMenu> trees = new ArrayList<>();

		List<RoleTreeMenu> roleMenus = qservice.findRoleTreeMenus(roleId);
		if(CollectionUtils.isNotEmpty(roleMenus)){
			if(DataUtils.convertToInt(roleId) == 0){
				roleMenus.stream().forEach(m -> m.setOwned(DomainConstants.YES));
			}
			
			trees.addAll(roleMenus);
		}
		
		TreeMenuView view = new TreeMenuView();

		String pageSuffix = systemRepository.getStringValue(SystemConfigRepository.PageSuffix);
		
		List<Menu> menus = UIHelper.convert(trees, pageSuffix);
		view.setMenus(menus);

		return view;
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	@InputLog
	public TreeMenuView getRoleList(int userId) throws Exception {
		TreeMenuView view = new TreeMenuView();
		
		List<AdminUserRole> userRoles = null;
		
		if(userId > 0){
			userRoles = repository.findAll(AdminUserRole.class);
			userRoles = Arrays.asList(userRoles.stream().filter(r -> r.getUserId() == userId).toArray(AdminUserRole[]::new));
		}
		
		List<AdminRole> roles = repository.findAll(AdminRole.class);
		roles = Arrays.asList(roles.stream()
				.filter(r -> AppEnv.getAppId().equals(r.getAppId()))
				.toArray(AdminRole[]::new));
				
		if(CollectionUtils.isNotEmpty(roles)){
			List<Menu> menus = new ArrayList<>();
			
			for(AdminRole role : roles){
				Menu menu = new Menu();
				
				menu.setId(role.getId());
				menu.setText(role.getRoleName());
				
				boolean checked = CollectionUtils.isNotEmpty(userRoles) ? userRoles.stream().anyMatch(r -> r.getRoleId() == role.getId()) : false;
				menu.setChecked(checked);
				
				menus.add(menu);
			}
			
			view.setMenus(menus);
		}
		
		return view;
	}
	
	@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
	@InputLog
	public UserOverviewView getUserOverviewView(int userId) throws Exception {
		UserOverviewView view = new UserOverviewView();
		
		AdminUser user = repository.findById(AdminUser.class, userId);
		
		List<LoginRole> roles = qservice.findLoginRoles(userId);

		view.setLoginName(user.getLoginName());
		view.setName(user.getName());
		view.setRoles(roles);
		
		return view;
	}
	
	@Transactional(rollbackFor=Throwable.class)
	public View changePassword(String loginName, String oldPassword, String newPassword) throws Exception {
		View view = new View();
		
		List<AdminUser> users = repository.find(AdminUser.class, ADMIN_USER_SQL, loginName, MD5.encrypt(oldPassword, loginName));
		AdminUser adminUser = CollectionUtils.isNotEmpty(users) ? users.get(0) : null;
		
		if(adminUser == null){
			throw new ValidationException("user " + loginName + " doesn't exits");
		}
		
		adminUser.setPassword(MD5.encrypt(newPassword, loginName));
		repository.save(adminUser);
		
		return view;
	}
	
	@Transactional(rollbackFor=Throwable.class)
	public View updateProfile(int userId, String name, String email) throws Exception {
		View view = new View();
		
		AdminUser adminUser = repository.findById(AdminUser.class, userId);
		
		if(adminUser == null){
			throw new ValidationException("user " + userId + " doesn't exits");
		}
		
		adminUser.setName(name);
		adminUser.setEmail(email);
		
		repository.save(adminUser);
		
		return view;
	}

	@Override
	public MenuListView getUserRoleMenuList(List<LoginRole> roles) throws Exception {
		MenuListView view = new MenuListView();
/*
		
		boolean isSuperRole = roles.stream().anyMatch(r -> SUPERROLE_NAME.equals(r.getRoleName()));
		List<Integer> rids = null;
				
		if(!isSuperRole){
			List<Integer> roleIds = new LinkedList<>();
			roles.stream()
				.forEach(r -> roleIds.add(r.getRoleId()));
			rids = roleIds;
		}
*/
//		List<Menu> menus = qservice.findUserRoleMenuList(rids);
		// 如果有权限分配菜单，一定是管理员，要显示所有菜单
		List<Menu> menus = qservice.findUserRoleMenuList();
		view.setMenus(menus);
		
		return view;
	}
	
}

